package config

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
)

// Config 应用程序配置
type Config struct {
	Server    ServerConfig    `json:"server"`
	Database  DatabaseConfig  `json:"database"`
	Scheduler SchedulerConfig `json:"scheduler"`
	Web       WebConfig       `json:"web"`
	Auth      AuthConfig      `json:"auth"`
	Language  string          `json:"language"` // 语言设置：en(英文) 或 zh(中文)
}

// ServerConfig 服务器配置
type ServerConfig struct {
	IP   string `json:"ip"`   // 监听IP地址
	Port string `json:"port"`
}

// DatabaseConfig 数据库配置
type DatabaseConfig struct {
	Path string `json:"path"` // SQLite数据库文件路径
}

// SchedulerConfig 调度器配置
type SchedulerConfig struct {
	MaxConcurrentTasks int `json:"maxConcurrentTasks"` // 最大并发任务数
	LogRetentionDays   int `json:"logRetentionDays"`   // 日志保留天数
}

// WebConfig 前端配置
type WebConfig struct {
	DistPath string `json:"distPath,omitempty"` // 可选：外部前端文件路径，留空则使用内嵌文件
}

// AuthConfig 认证配置
type AuthConfig struct {
	Username string `json:"username"` // 登录用户名
	Password string `json:"password"` // MD5加密后的密码
	Salt     string `json:"salt"`     // 密码盐
}

// EncryptPassword 加密密码（MD5+盐）
func (a *AuthConfig) EncryptPassword(password string) string {
	return encryptPassword(password, a.Salt)
}

// ValidateCredentials 验证用户凭据
func (a *AuthConfig) ValidateCredentials(username, encryptedPassword string) bool {
	return username == a.Username && encryptedPassword == a.Password
}

// DefaultConfig 默认配置
var DefaultConfig = getDefaultConfigStatic()

// getDefaultConfigStatic 获取静态默认配置（用于全局变量初始化）
func getDefaultConfigStatic() Config {
	return Config{
	Server: ServerConfig{
		IP:   "0.0.0.0",
		Port: "3001",
	},
	Database: DatabaseConfig{
			Path: "./skedule.db", // 这里保持相对路径，实际使用时会通过getDefaultConfig()重新生成
	},
	Scheduler: SchedulerConfig{
		MaxConcurrentTasks: 5,
		LogRetentionDays:   30,
	},
	Web: WebConfig{
		DistPath: "", // 空字符串表示使用内嵌文件系统
	},
	Auth: AuthConfig{
		Username: "admin",
		Password: encryptPassword("admin", "skedule2024"),
		Salt:     "skedule2024",
	},
	Language: "en",
	}
}

// GetExecutableDir 获取可执行文件所在目录
func GetExecutableDir() (string, error) {
	exe, err := os.Executable()
	if err != nil {
		return "", err
	}
	return filepath.Dir(exe), nil
}

// LoadConfigFromFile 从JSON文件加载配置
func LoadConfigFromFile(configPath string) (*Config, error) {
	data, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read configuration file: %v", err)
	}

	var config Config
	if err := json.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("failed to parse configuration file: %v", err)
	}

	return &config, nil
}

// SaveConfigToFile 保存配置到JSON文件
func SaveConfigToFile(config *Config, configPath string) error {
	data, err := json.MarshalIndent(config, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to serialize configuration: %v", err)
	}

	if err := os.WriteFile(configPath, data, 0644); err != nil {
		return fmt.Errorf("failed to write configuration file: %v", err)
	}

	return nil
}

// GetConfig 获取配置
func GetConfig() (*Config, error) {
	// 首先尝试从可执行文件同目录读取配置文件
	configPath, err := getConfigPath()
	if err != nil {
		return nil, fmt.Errorf("failed to get configuration file path: %v", err)
	}

	// 如果配置文件不存在，创建默认配置
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		fmt.Printf("Configuration file not found, creating default config: %s\n", configPath)
		config := getDefaultConfig()
		if err := saveConfig(config, configPath); err != nil {
			return nil, fmt.Errorf("failed to save default configuration: %v", err)
		}
		return config, nil
	}

	// 读取配置文件
	data, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read configuration file: %v", err)
	}

	var config Config
	if err := json.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("failed to parse configuration file: %v", err)
	}

	// 处理数据库路径：如果是相对路径，转换为基于可执行文件目录的路径
	if err := normalizePaths(&config); err != nil {
		return nil, fmt.Errorf("failed to normalize paths: %v", err)
	}

	// 应用环境变量覆盖
	applyEnvOverrides(&config)

	// 验证配置
	if err := validateConfig(&config); err != nil {
		return nil, fmt.Errorf("configuration validation failed: %v", err)
	}

	return &config, nil
}

// getConfigPath 获取配置文件路径（可执行文件同目录）
func getConfigPath() (string, error) {
	// 获取可执行文件路径
	execPath, err := os.Executable()
	if err != nil {
		return "", err
	}

	// 获取可执行文件所在目录
	execDir := filepath.Dir(execPath)
	
	// 配置文件在同目录下
	configPath := filepath.Join(execDir, "config.json")
	
	return configPath, nil
}

// getDefaultConfig 获取默认配置
func getDefaultConfig() *Config {
	// 获取可执行文件所在目录
	execDir, err := GetExecutableDir()
	if err != nil {
		// 如果获取失败，使用当前目录作为后备方案
		execDir = "."
	}
	
	// 数据库文件路径基于可执行文件目录
	dbPath := filepath.Join(execDir, "skedule.db")
	
	return &Config{
		Server: ServerConfig{
			IP:   "0.0.0.0",
			Port: "3001",
		},
		Database: DatabaseConfig{
			Path: dbPath,
		},
		Scheduler: SchedulerConfig{
			MaxConcurrentTasks: 5,
			LogRetentionDays:   30,
		},
		Web: WebConfig{
			DistPath: "", // 空字符串表示使用内嵌文件系统
		},
		Auth: AuthConfig{
			Username: "admin",
			Password: encryptPassword("admin", "skedule2024"),
			Salt:     "skedule2024",
		},
		Language: "en",
	}
}

// applyEnvOverrides 应用环境变量覆盖
func applyEnvOverrides(config *Config) {
	if port := os.Getenv("PORT"); port != "" {
		config.Server.Port = port
	}
	
	if dbPath := os.Getenv("DATABASE_PATH"); dbPath != "" {
		config.Database.Path = dbPath
	}
	
	if distPath := os.Getenv("DIST_PATH"); distPath != "" {
		config.Web.DistPath = distPath
	}
	
	if host := os.Getenv("HOST"); host != "" {
		config.Server.IP = host
	}
}

// validateConfig 验证配置
func validateConfig(config *Config) error {
	if config.Server.IP == "" {
		return fmt.Errorf("IP address cannot be empty")
	}
	
	if config.Server.Port == "" {
		return fmt.Errorf("port cannot be empty")
	}
	
	if config.Database.Path == "" {
		return fmt.Errorf("database path cannot be empty")
	}
	
	return nil
}

// saveConfig 保存配置到文件
func saveConfig(config *Config, configPath string) error {
	data, err := json.MarshalIndent(config, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to serialize configuration: %v", err)
	}

	if err := os.WriteFile(configPath, data, 0644); err != nil {
		return fmt.Errorf("failed to write configuration file: %v", err)
	}

	return nil
}

// normalizePaths 标准化配置中的路径，确保相对路径基于可执行文件目录
func normalizePaths(config *Config) error {
	// 获取可执行文件目录
	execDir, err := GetExecutableDir()
	if err != nil {
		return err
	}

	// 处理数据库路径
	if !filepath.IsAbs(config.Database.Path) {
		// 如果是相对路径，基于可执行文件目录
		config.Database.Path = filepath.Join(execDir, config.Database.Path)
	}

	// 处理前端文件路径（如果指定了外部路径）
	if config.Web.DistPath != "" && !filepath.IsAbs(config.Web.DistPath) {
		config.Web.DistPath = filepath.Join(execDir, config.Web.DistPath)
	}

	return nil
}

// encryptPassword 加密密码（MD5+盐）
func encryptPassword(password, salt string) string {
	// 将密码和盐拼接
	data := []byte(password + salt)
	
	// 计算MD5
	hash := md5.Sum(data)
	
	// 转换为16进制字符串
	return hex.EncodeToString(hash[:])
} 